import org.codehaus.groovy.grails.plugins.authorize.user.AuthUserStatus;

class RegisterController {

    AuthEmailService authEmailService

    def index = {
        render(view: 'register', model: [user: new AuthUser()])
    }

    // This closure returns the view to use to register with
    def register = {
        render(view: 'register', model: [user: new AuthUser()])
    }

    // This closure creates the initial user record, and sends the confirmation email
    def doRegister = { AuthUserValidationCommand cmd ->
        AuthUser user = new AuthUser();
        user.properties = params;

        if (cmd.hasErrors()) {
            cmd.errors.each {
                log.debug it
            }
            render(view: 'register', model: [user: new AuthUser()], params: params)
            return
        }

        // Create the user
        user.passwordEnc = params.password.encodeAsPassword()
        user.hash = "${user.username}:${user.email}:${new Date()}".encodeAsPassword()

        // We want to prevent the user from being saved if the email is not sent successfully
        AuthUser.withTransaction {status ->
            // Save the user, and return to the input view if there is a problem saving the user
            if (!user.save()) {
                render(view: 'register', model: [user: user])
                status.setRollbackOnly()
                return;
            }

            log.debug "Sending email via ${grailsApplication.config.authorize?.smtp?.host}:${grailsApplication.config.authorize?.smtp?.username}:${grailsApplication.config.authorize?.smtp?.password}"
            log.debug "              to ${user.email}"

            // User record saved, so send the confirmation email - something along these lines
            try {
                def serverPortStr = request.serverPort == 80 ? "" : ":${request.serverPort}"
                def confirmUrl = "${request.scheme}://${request.serverName}${serverPortStr}/${request.contextPath}/register/confirm?uid=${user.hash.encodeAsURL()}"
                def emailContent = g.render(template: "/register/emails/confirm", model: [user: user, confirmUrl: confirmUrl])
                log.debug "              msg: ${emailContent}"
                String fromAddr = grailsApplication.config.authorize?.smtp?.from
                authEmailService.sendMail(fromAddr, user.email, "Please confirm your registration", emailContent)
                flash.message = "authorize.register.confirmation.email.sent"
            } catch (Exception e) {
                e.printStackTrace()
                status.setRollbackOnly()
                flash.message = "authorize.register.confirmation.email.not.sent"
            }
        }


        def successController = grailsApplication.config.authorize.register.success.controller
        def successAction = grailsApplication.config.authorize.register.success.action
        if (successController && successAction) {
            chain(controller:successController, action:successAction)
            return
        }

        redirect(uri: "/")
    }

    def confirm = {
        String id = params.uid

        if (id == null) {
            flash.message = "authorize.register.uid.not.present"
            redirect(uri: "/")
            return
        }

        def user = AuthUser.findWhere(hash: id)
        if (user == null) {
            flash.message = "authorize.register.uid.not.found"
            redirect(uri: "/")
            return
        }

        if (user.status == AuthUserStatus.ACTIVE) {
            flash.message = "authorize.register.account.active";
            redirect(uri: "/")
            return;
        }

        if (user.status == AuthUserStatus.INACTIVE) {
            flash.message = "authorize.register.account.inactive"
            redirect(uri: "/")
            return;
        }

        if (user.status == AuthUserStatus.SUSPENDED) {
            flash.message = "authorize.register.account.suspended"
            redirect(uri: "/")
            return;
        }

        if (user.status == AuthUserStatus.EXPELLED) {
            flash.message = "authorize.register.account.expelled"
            redirect(uri: "/")
            return;
        }

        user.status = AuthUserStatus.ACTIVE;
        if (user.save()) {
            flash.message = "authorize.register.account.finalized";
            flash.args = [user.firstname]

            // TODO : Send a confirmation email here
            log.debug "Sending email via ${grailsApplication.config.authorize.smtp.host}:${grailsApplication.config.authorize.smtp.username}:${grailsApplication.config.authorize.smtp.password}"
            log.debug "              to ${user.email}"

            // User record saved, so send the confirmation email - something along these lines
            try {
                def serverPortStr = request.serverPort == 80 ? "" : ":${request.serverPort}"
                def emailContent = g.render(template: "/register/emails/confirmed", model: [user: user])
                log.debug "              msg: ${emailContent}"
                authEmailService.sendMail(grailsApplication.config.authorize.smtp.from, user.email, "Your registration is confirmed", emailContent)
            } catch (Exception e) {
                e.printStackTrace()
            }

            // TODO: Maybe prompt the user as to whether they want to login, or continue browsing.

        } else {
            user.errors.each {error ->
                log.error("Error: ${error}")
            }
            flash.message = "authorize.register.account.cant.finalize"
        }
        
        redirect(uri: "/")
    }

}

class AuthUserValidationCommand {

    String username
    String password
    String passwordagain
    String email
    String firstname
    String lastname

    static constraints = {
        username(blank: false, minSize: 3)
        password(blank: false, minSize: 6, validator: {
            val, obj ->
            obj.properties['passwordagain'] == val
        })
        passwordagain(blank: false, minSize: 6)
        email(blank: false)
        firstname(blank: true)
        lastname(blank: true)
    }
}